package testrj.traverser.genericstrategies;

import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;

import testrj.traverser.ObjectTraverser;
import testrj.util.ReflectionUtils;

public abstract class GenericFieldBasedNodeStrategy extends AbstractStrategy {

	public void handle(Object object, ObjectTraverser traverser) {
		List<Field> fields = ReflectionUtils.getAllFieldsIn(object);
		boolean pendingHasMoreElements = false;
		if (fields != null) {
			Iterator<Field> iter = fields.iterator();
			while (true) {
				if (!iter.hasNext())
					break;
				Field field = iter.next();
				if (ReflectionUtils.isTransient(field))
					continue;
				if (!field.isAccessible()) {
					field.setAccessible(true);
				}
				if (exclude(field)) {
					continue;
				}
				if (include(field)) {
					if (pendingHasMoreElements) {
						hasMoreElements();
						pendingHasMoreElements = false;
					}
					handleField(field, object, traverser);
				}
				if (include(field) && iter.hasNext()) {
					pendingHasMoreElements = true;
				}
			}
		}
	}

	public void handleField(Field field, Object object, ObjectTraverser traverser) {
		try {
			traverser.traverse(field.get(object));
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void hasMoreElements() {
	}

	public boolean include(Field field) {
		return true;
	}

	public boolean exclude(Field field) {
		return false;
	}

	public boolean canHandle(Object object) {
		return true;
	}
}